package com.imooc.SmartChargeStation.demo.mqtt.FacoryMode.factory;

import com.imooc.SmartChargeStation.demo.mqtt.FacoryMode.conf.MqttProps;
import com.imooc.SmartChargeStation.demo.mqtt.FacoryMode.model.MqttConstants;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;

import javax.swing.*;

/**
 * author: zpy
 * description: MQTT 工厂类
 * date: 2025/8/18
 */

@Configuration
/*
    标识当前类是 Spring 的配置类，Spring 会扫描并加载该类中定义的 Bean（通过@Bean注解的方法）。
 */
@EnableIntegration
/*
    @EnableIntegration：启用 Spring Integration 框架功能。
    Spring Integration 是基于企业集成模式（EIP）的框架，用于实现系统间的消息交互，此处用于整合 MQTT 协议。
 */
@Slf4j
public class FactoryBuilder {
/*
    怎么理解MQTT 客户端工厂模式？
    答：MQTT 客户端的创建需要一系列复杂且固定的配置步骤（如指定服务器地址、设置连接超时、心跳间隔、客户端 ID 等），
    而工厂模式的核心就是：将这些复杂的创建和配置逻辑 “打包” 到一个专门的 “工厂” 中，
    让工厂统一负责 MQTT 客户端（或客户端工厂）的生产，
    使用者只需 “调用工厂” 即可获取配置好的客户端，无需关心内部细节。
 */
    @Resource
    private MqttProps props;

    /**
     * description: 获取Mqtt客户端
     * @param :
     * @return org.springframework.integration.mqtt.core.MqttPahoClientFactory
     */
    @Bean
/*
    标识该方法会生成一个 Bean，并注册到 Spring 容器中，其他组件可通过依赖注入使用该工厂。
 */

    /**
     * 创建Mqtt客户端工厂
     * @return
     */
    public MqttPahoClientFactory getFactory() {
        //创建工厂实例
        DefaultMqttPahoClientFactory client = new DefaultMqttPahoClientFactory();
        //获取连接配置
        MqttConnectOptions options = props.getOptions();
        //配置服务器地址
        options.setServerURIs(new String[]{props.getHost()});
        //将配置好的连接选项 options 注入到 MQTT 客户端工厂 client 中
        client.setConnectionOptions(options);
        //返回配置完成的 MQTT 客户端工厂实例
        return client;

    }
/*
    Spring Integration 如何整合 MQTT？
    答：Spring Integration 是基于 “消息驱动” 的框架，它通过 “通道（Channel）”“处理器（Handler）”“适配器（Adapter）” 等组件，
    将 “外部系统（这里是 MQTT 服务器）” 与 “应用内部逻辑” 连接起来。
 */

    /*信息通道*/
    /**
     * description: 发送通道
     * @param :
     * @return org.springframework.messaging.MessageChannel
     */
    @Bean(name = MqttConstants.OUT_CHANNEL)
    public MessageChannel outChannel() {

        return new DirectChannel();
    }


    /**
     * description: 接收通道
     * @param :
     * @return org.springframework.messaging.MessageChannel
     */
    @Bean(name = MqttConstants.In_CHANNEL)
    public MessageChannel inChannel() {

        return new DirectChannel();
    }


    /*发送信息*/
    @Bean
    @ServiceActivator(inputChannel = MqttConstants.OUT_CHANNEL)
/*
    将被标注的Bean（或者方法返回的Bean）注册为消息处理器，并指定这个处理器监听哪个消息通道（inputChannel）
    的消息。当指定的消息到达时，Spring Integration 会自动将消息传递给这个处理器，由处理器执行具体的业务逻辑
 */
    public MqttPahoMessageHandler outHandler() {

        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(props.getClientIdFactoryMode(),getFactory());

        log.info(">>>>>工厂模式发送消息处理器生成状态 "+messageHandler.toString());

        return messageHandler;
    }

    /*接收消息*/
    @Bean
    @ServiceActivator(inputChannel = MqttConstants.In_CHANNEL)
    public MessageHandler inHandler(){

       return new MessageHandler() {
            @Override
            public void handleMessage(Message<?> message) throws MessagingException {

                log.info(message.getPayload().toString());
            }
        };
    }

    /**
     * description: 订阅主题的适配器
     * @param :
     * @return org.springframework.integration.core.MessageProducer
     */
    @Bean
    public MessageProducer getAdapter() {

        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(props.getClientIdFactoryMode(), getFactory(), props.getTopic());

        //设置转换器
        adapter.setConverter(new DefaultPahoMessageConverter());
        //设置订阅通道
        adapter.setOutputChannel(inChannel());

        log.info(">>>>>工厂模式订阅主题适配器生成状态 "+adapter.toString());

        return adapter;
    }
}
